//
//  Person.swift
//  Study Swift
//
//  Created by admin on 2019/8/6.
//  Copyright © 2019 猫爷爷的酱醋茶. All rights reserved.
//

import UIKit

/*
 构造函数 - 建立一个对象
 1.给属性分配空间
 2.设置初始值
 
 Swift 中的构造函数’都‘是 init
 
 重载：OC中没有重载的概念
    - 函数名相同，参数的个数和类型不同，叫做重载。是面向对象设计语言必备标志！
 
 OC中用initWithXxx替代
 
 */


class Person: NSObject
{
    //对象的属性就是应该可变的
    //可选项，允许变量为空，var 的默认值为nil
    //在iOS开发中，所有的属性是延迟加载的
    @objc var name: String?
    
//MARK: getter 和 setter
    //在swift中极少用，仅供参考

//        @objc var _name: String?
//
//        //---getter 和 setter----方法在swift中极少用，仅供参考
//        var name:String?
//        {
//            set //使用 _成员变量记录新的数值
//            {
//                _name = newValue
//            }
//
//            get //返回 _成员变量的值
//            {
//                return _name;
//            }
//        }
    
//MARK: 计算型属性
    //readOnly 属性 - 只写getter方法
    var title:String?
    {
        get
        {
            return "Mr " + (name ?? "")
        }
    }
    
    /*
        另一种叫法 - “计算型属性”
        每一次调用的时候，都会执行{}中的代码，‘结果取决于其他属性或者原因’
        每次都要计算，浪费性能
        但是不需要开辟额外的空间
      - 如果计算量很小，推荐使用计算型属性
      - 如果计算量很大，推荐使用懒加载
     */
    //只读属性的简写方法 - 如果属性的‘修饰’方法，只提供getter，那么get{}可以省略
    var title2:String?
    {
        return "Mr " + (name ?? "")
    }
    
    //age 和KVC不兼容 OC中Int属于基本数据类型，不存在‘nil’的概念
//    var age: Int?
    
    //所以在KVC方法中，所有基本数据类型的数据都要初始化
   @objc var age: Int = 0
    
    
//MARK: 析构函数
    /*
     析构函数
        与OC中的dealloc 对象的释放方法类似，主要是负责对象被销毁之前的‘内存释放’的工作
        deinit - 没有func 也没有()
            -> 不允许被重载，不允许带参数，不允许直接调用，在系统内部自动调用的
     
        在实际开发中，哪些内容需要程序员销毁？
        - 通知，如果不销毁，程序不会崩溃
        - KVO，如果不销毁，程序会崩溃
        - NSTimer 会对target(self) 进行强引用
     
     
     */
    //析构函数
    deinit {
        print("Person 88")
    }
    
//MARK: 遍历构造函数
    /*
     convenience - 便利构造函数
        - 能够提供条件检测
        - 能够允许返回nil
        - 便利构造函数必须在条件检测完成之后，以self.调用其他的构造函数，创建对象
        - 能够简化对象的创建方法
        - 便利构造函数，不能被继承，也不能被重写（但如果子类没有便利构造函数，会调用父类的）
     */
    convenience init?(name:String,age:Int)
    {
        if age < 0 || age > 100
        {
            //不能创建对象
            return nil
        }
        
        //self 是当前类的方法，如果是子类调用就是子类的方法
        self.init(dict:["name":name as AnyObject,"age":age as AnyObject])
    }
    
    
    //重写默认的构造函数
    //父类提供了这个函数，而子类需要对父类的函数进行扩展，就叫做重写。
    //override 重写父类方法
    override init()
    {
        name = "猫爷爷的酱醋茶"
        age = 22

        //调用父类的构造函数
        super.init()
    }

    //重载的构造函数 - 只要是构造函数，就需要给属性设置初始值
    //如果重写了构造函数，系统默认提供的，就不能访问了。
//    init(name:String,age:Int)
//    {
//        self.name = name
//        self.age = age
//    }
    

//MARK: 以下所有函数都是，KVC函数的调用顺序
    init(dict:[String:AnyObject])
    {
        //KVC 是OC特有的
        //本质是在运行时，动态的给‘对象’发送‘setValue:forKey:’消息 设置数值
        //既然是给‘对象’发送，那就要确保对象存在，故需要先super.init() 初始化父类方法
        super.init() //该语句结束后，name并不会被分配空间
        
        
        //当给对象发送setValue:forKey:消息的时候
        //会先判断属性时候已经“实例化”
        //如果已经实例化了 -> 直接赋值
        //如果没有实例化 -> 调用属性对象的构造函数实例化属性 再设置数值
        setValuesForKeys(dict)
        
        
    }
    
    //重写这个方法，可以看到 setValuesForKeys 的实现方法
    override func setValue(_ value: Any?, forKey key: String) {
        super.setValue(value, forKey: key)
    }
    
    //默认的 setValue forUndefinedKey 方法如果出现未定义的key 会报错
    //如果一旦重写了此方法，同时不super，不调用父类默认的方法
    override func setValue(_ value: Any?, forUndefinedKey key: String) {
        
    }
    
    
}

